package cn.bupt.adt.controller.inf;

import cn.bupt.adt.constant.Constants;
import cn.bupt.adt.entity.autogenerate.DoctorAppUser;
import cn.bupt.adt.entity.autogenerate.UserAgreement;
import cn.bupt.adt.entity.autogenerate.Withdraw;
import cn.bupt.adt.service.IDoctorAppUserService;
import cn.bupt.adt.service.IDoctorService;
import cn.bupt.adt.service.IUserAgreementService;
import cn.bupt.adt.service.IWithdrawService;
import cn.bupt.adt.util.*;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import redis.clients.jedis.Jedis;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/publicApp/doctor")
public class DoctorAppPublicController {

    @Autowired
    IDoctorAppUserService doctorAppUserService;

    @Autowired
    IDoctorService doctorService;

    @Autowired
    IWithdrawService withdrawService;

    @Autowired
    IUserAgreementService userAgreementService;

    @RequestMapping("/login")
    @ResponseBody
    //注册需要填写账号account，密码passwd
    public Object login(DoctorAppUser user, HttpServletRequest request) {
        NetDataAccessUtil nau = new NetDataAccessUtil();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if ("GET".equals(request.getMethod()) || null == user) {
            nau.setContent(null);
            nau.setResult(-3);
            nau.setResultDesp("请求错误！");
        } else {
            DoctorAppUser doc = doctorAppUserService.getDoctorByAccount(user.getAccount());
            if (doc == null) {
                //用户未注册
                nau.setContent(null);
                nau.setResult(-1);
                nau.setResultDesp("该用户不存在！");

            } else {
                if (!doc.getPasswd().equals(MD5Util.MD5(user.getPasswd()))) {
                    //密码不正确
                    nau.setContent(null);
                    nau.setResult(-2);
                    nau.setResultDesp("密码错误！");
                } else {
                    if (!doc.getReviewStatus()) {
                        nau.setContent(-3);
                        nau.setResultDesp("该账号信息尚未被审核，无法登陆");
                    } else {
                        //登录成功，清除之前的token信息
                        Jedis redis = RedisUtil.getJedis();
                        Date loginTime = new Date();
                        String key = UserUtil.generateToken(user.getAccount(), df.format(loginTime));
                        if (redis.exists(key)) {
                            redis.del(key);
                            RedisUtil.returnResource(redis);
                        }
                        doctorAppUserService.updateLoginTimeById(doc.getId(), loginTime);
                        //生成token,存token到redis
                        String token = UserUtil.generateToken(user.getAccount(), df.format(loginTime));
                        RedisUtil.set(token, doc.getId());
                        //事先拼接用户图像的完整路径
                        doc.setPortrait("http://" + IPUtil.getIpAddr(request) + ":" + request.getLocalPort() + "/" + Constants.IMAGE_PATH + doc.getPortrait());
                        //返回信息
                        nau.setContent(UserUtil.constructUserResp(doc, token));
                        nau.setResult(1);
                        nau.setResultDesp("登录成功");
                    }
                }
            }
        }
        return nau;
    }

    /**
     * 跳过redis处理逻辑的登录
     *
     * @param user
     * @param request
     * @return
     */
    @RequestMapping("/testlogin")
    @ResponseBody
    public Object testLogin(DoctorAppUser user, HttpServletRequest request) {
        NetDataAccessUtil nau = new NetDataAccessUtil();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if ("GET".equals(request.getMethod()) || null == user) {
            nau.setContent(null);
            nau.setResult(-3);
            nau.setResultDesp("请求错误！");
        } else {
            DoctorAppUser doc = doctorAppUserService.getDoctorByAccount(user.getAccount());
            if (doc == null) {
                //用户未注册
                nau.setContent(null);
                nau.setResult(-1);
                nau.setResultDesp("该用户不存在！");

            } else {
                if (!doc.getPasswd().equals(MD5Util.MD5(user.getPasswd()))) {
                    //密码不正确
                    nau.setContent(null);
                    nau.setResult(-2);
                    nau.setResultDesp("密码错误！");
                } else {
                    if (!doc.getReviewStatus()) {
                        nau.setContent(-3);
                        nau.setResultDesp("该账号信息尚未被审核，无法登陆");
                    } else {
                        //登录成功，清除之前的token信息
//						Jedis redis = RedisUtil.getJedis();
                        Date loginTime = new Date();
                        String key = UserUtil.generateToken(user.getAccount(), df.format(loginTime));
//				        if( redis.exists(key)){
//					        redis.del(key);
//					        RedisUtil.returnResource(redis);
//				        }
                        doctorAppUserService.updateLoginTimeById(doc.getId(), loginTime);
                        //生成token,存token到redis
//				        String token =UserUtil.generateToken(user.getAccount(),df.format(loginTime));
//				        RedisUtil.set(token,doc.getId());
                        //事先拼接用户图像的完整路径
                        doc.setPortrait("http://" + IPUtil.getIpAddr(request) + ":" + request.getLocalPort() + "/" + Constants.IMAGE_PATH + doc.getPortrait());
                        //返回信息
                        nau.setContent(UserUtil.constructUserResp(doc, "test0000"));
                        nau.setResult(1);
                        nau.setResultDesp("登录成功");
                    }
                }
            }
        }
        return nau;
    }

    @RequestMapping(value = "/validInviteCode", method = RequestMethod.POST)
    @ResponseBody
    public Object validInviteCode(HttpServletRequest request, DoctorAppUser user) {
        NetDataAccessUtil nau = new NetDataAccessUtil();
        DoctorAppUser docAlready = doctorAppUserService.checkInviteCode(user.getInvitaCode());
        Map<String, Object> content = new HashMap<>();
        if (docAlready == null) {
            //邀请码不正确
            content.put("flag", false);
            nau.setContent(content);
            nau.setResult(0);
            nau.setResultDesp("邀请码不正确，请输入邀请码");
        } else {
            if (docAlready.getAccount() == null) {
                content.put("flag", true);
                nau.setContent(content);
                nau.setResult(1);
                nau.setResultDesp("验证成功");
            } else {
                content.put("flag", false);
                nau.setContent(content);
                nau.setResult(0);
                nau.setResultDesp("该邀请码已被使用，无法使用该邀请码注册");
            }

        }
        return nau;
    }

    @RequestMapping(value = "/validAccount", method = RequestMethod.POST)
    @ResponseBody
    public Object validAccount(DoctorAppUser user) {
        DoctorAppUser docAlready = doctorAppUserService.getDoctorByAccount(user.getAccount());
        Map<String, Object> content = new HashMap<>();
        if (docAlready != null) {
            //账号已存在
            content.put("flag", false);
            return NetDataAccessUtil.error().content(content).resultDesp("该账号已存在，请重新输入新的账号");
        } else {
            content.put("flag", true);
            return NetDataAccessUtil.success().content(content).resultDesp("该账号尚未被注册，可以使用");
        }
    }

    //注册需要填写邀请码invitaCode，账号account，密码passwd
    @ResponseBody
    @RequestMapping(value = "/regist", method = RequestMethod.POST)
    //@ApiOperation(value = "医生注册", httpMethod = "POST", response = NetDataAccessUtil.class, notes = "regist")
    public Object register(HttpServletRequest request, DoctorAppUser user, String operationTypes) {
        NetDataAccessUtil nau = new NetDataAccessUtil();
        if (doctorAppUserService.getDoctorByAccount(user.getAccount()) != null) {
            //若账号已经存在，要求重新注册
            nau.setContent(null);
            nau.setResult(0);
            nau.setResultDesp("账号已被注册过，请重新输入账号");
        } else {
            DoctorAppUser docAlready = doctorAppUserService.checkInviteCode(user.getInvitaCode());
            if (docAlready == null) {
                //邀请码不正确
                nau.setContent(null);
                nau.setResult(-1);
                nau.setResultDesp("邀请码不正确，请输入邀请码");
            } else {
                if (docAlready.getAccount() != null) {
                    //邀请码已经被使用过
                    nau.setContent(null);
                    nau.setResult(-1);
                    nau.setResultDesp("邀请码已被使用，无法再使用该邀请码注册");
                    return nau;
                }
                //邀请码正确
                user.setPasswd(MD5Util.MD5(user.getPasswd()));
                user.setMoney(0.0);
                user.setRiskMargin(0.0);
                user.setWaitedToBeWithdrawnMoney(0.0);
                user.setOperationSuccessNum(0);
                user.setId(docAlready.getId());
                user.setReviewStatus(false);
                ObjectMapper oMapper = new ObjectMapper();
                int[] operationTypesId = null;
                try {
                    operationTypesId = oMapper.readValue(operationTypes, int[].class);
                } catch (JsonParseException e) {
                    nau.setContent(null);
                    nau.setResult(0);
                    nau.setResultDesp("operationTypes传递形式有错,请以[typeid1,typeid2...]传递");
                    return nau;
                } catch (JsonMappingException e) {
                    nau.setContent(null);
                    nau.setResult(0);
                    nau.setResultDesp("解析错误");
                    return nau;
                } catch (IOException e) {
                    nau.setContent(null);
                    nau.setResult(0);
                    nau.setResultDesp("IO异常");
                    return nau;
                }
                if (!doctorAppUserService.addDoctorAppUser(user, operationTypesId, request)) {
                    nau.setContent(null);
                    nau.setResult(-2);
                    nau.setResultDesp("注册失败");
                } else {
                    nau.setContent(null);
                    nau.setResult(1);
                    nau.setResultDesp("注册成功");
                }
            }
        }
        return nau;
    }

    @RequestMapping(value = "/logout", method = RequestMethod.POST)
    @ResponseBody
    public Object logout(HttpServletRequest request) {
        NetDataAccessUtil nau = new NetDataAccessUtil();
        Integer userId = (Integer) request.getAttribute("userId");
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        DoctorAppUser doc = doctorAppUserService.getDoctorById(userId);
        String key = MD5Util.MD5(doc.getAccount() + df.format(doc.getLoginTime()));
        if (RedisUtil.exist(key)) {
            RedisUtil.del(key);
            return NetDataAccessUtil.success().resultDesp("登出成功！");
        }
        return NetDataAccessUtil.error().resultDesp("登出失败！");
    }

    @RequestMapping(value = "/changePasswd", method = RequestMethod.POST)
    @ResponseBody
    //修改密码需要传入token，旧密码passwd,新密码newPasswd
    public Object changePasswd(HttpServletRequest request, String passwd, String newPasswd) {
        Integer userId = (Integer) request.getAttribute("userId");
        DoctorAppUser doc = doctorAppUserService.getDoctorById(userId);
        if (!MD5Util.MD5(passwd).equals(doc.getPasswd())) {
            //输入原密码不对
            return NetDataAccessUtil.error().resultDesp("输入旧密码不正确，请确认您的旧密码");
        }
        if (doctorAppUserService.changePasswd(doc, newPasswd)) {
            RedisUtil.del(request.getParameter("token"));
            return NetDataAccessUtil.success().resultDesp("修改密码成功,请重新登录");
        }
        return NetDataAccessUtil.error().resultDesp("因网络或其他原因，修改密码失败，请稍后尝试");
    }

    @RequestMapping(value = "/askForValidateCodeToResetPasswd", method = RequestMethod.POST)
    @ResponseBody
    //重置密码，传入手机号,向该手机号发送验证码
    public Object askForValidateCodeToResetPasswd(HttpServletRequest request, String phone) {
        NetDataAccessUtil nau = new NetDataAccessUtil();
        doctorAppUserService.sendSmsForResetPasswd(phone, nau);
        return nau;
    }

    @RequestMapping(value = "/resetPasswd", method = RequestMethod.POST)
    @ResponseBody
    //重置密码，传入验证码
    public Object resetPasswd(HttpServletRequest request, String validateCode) {
        NetDataAccessUtil nau = new NetDataAccessUtil();
        if (RedisUtil.exist(validateCode)) {
            Integer docId = Integer.parseInt((String) RedisUtil.get(validateCode));
            if (doctorService.resetDoctorPasswdById(docId)) {
                nau.setResult(1);
                nau.setResultDesp("重置密码成功，新密码为123456");
                RedisUtil.del(validateCode);
            } else {
                nau.setResult(2);
                nau.setResultDesp("因网络或其他原因，重置密码失败");
            }
        } else {
            nau.setResultDesp("验证码错误");
            nau.setResult(0);
        }
        return nau;
    }

    @RequestMapping(value = "/withdraw", method = RequestMethod.POST)
    @ResponseBody
    public Object withdraw(HttpServletRequest request, Withdraw withdraw) {
        Integer userId = (Integer) request.getAttribute("userId");
        DoctorAppUser doc = doctorAppUserService.getDoctorById(userId);
        if (doc.getMoney() < withdraw.getMoney()) {
            return NetDataAccessUtil.error().resultDesp("可提现余额小于提现金额，无法提现，请重新输入提现金额");
        }
        withdraw.setDealed(Constants.Withdraw_Undealed);
        withdraw.setFlag(Constants.DOC_WITHDRAW);
        withdraw.setUserId(userId);
        withdraw.setTime(new Date());
        if (withdrawService.addWithdraw(withdraw, doc)) {
            return NetDataAccessUtil.success().resultDesp("提现申请成功，将于2-3个工作日内到账");
        }
        return NetDataAccessUtil.error().resultDesp("因网络或其他错误，提现失败，请稍后尝试");
    }

    /**
     * 获取医生个人信息
     *
     * @param userId
     * @param token
     * @param request
     * @return
     */
    @RequestMapping(value = "/getDoctorInfo", method = RequestMethod.POST)
    @ResponseBody
    public Object getDoctorInfo(Integer userId, String token, HttpServletRequest request) {
        DoctorAppUser doc = doctorAppUserService.getDoctorById(userId);
        if (doc != null) {
            doc.setPortrait("http://" + IPUtil.getIpAddr(request) + ":" + request.getLocalPort() + "/" + Constants.IMAGE_PATH + doc.getPortrait());
            return NetDataAccessUtil.success().content(UserUtil.constructUserResp(doc, token)).resultDesp("获取医生个人信息成功");
        }
        return NetDataAccessUtil.error().resultDesp("获取医生个人信息失败");
    }

    @RequestMapping(value = "/getUserAgreement", method = RequestMethod.POST)
    @ResponseBody
    public Object getUserAgreement(HttpServletRequest request) {
        String content = "http://" + IPUtil.getIpAddr(request) + ":" + request.getLocalPort() + request.getContextPath() + "/publicApp/doctor/userAgreement";
        return NetDataAccessUtil.success().content(content).resultDesp("获取用户协议成功");
    }

    @RequestMapping("/userAgreement")
    public ModelAndView userAgreement() {
        ModelAndView mv = new ModelAndView(Constants.USERAGREEMENT_H5);
        UserAgreement u = userAgreementService.getUserAgreement();
        if (u != null)
            mv.addObject("detail", u.getContent());
        return mv;
    }

}
